package com.health.service.Impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.health.context.BaseContext;
import com.health.entity.UsersAccount;
import com.health.entity.UsersTrade;
import com.health.mapper.UserMapper;
import com.health.mapper.UsersAccountMapper;
import com.health.mapper.UsersTradeMapper;
import com.health.properties.WeChatProperties;
import com.health.service.PayService;
import com.health.utils.PayUtil;
import com.health.vo.OrderPaymentVO;
import com.health.vo.TradeAndAccountVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class PayServiceImpl implements PayService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UsersTradeMapper usersTradeMapper;

    @Autowired
    private PayUtil payUtil;

    @Autowired
    private WeChatProperties weChatProperties;

    @Autowired
    private UsersAccountMapper usersAccountMapper;


    @Override
    @Transactional
    public OrderPaymentVO pay(Integer money) throws Exception {
        log.info("money:{}",money);
        Long userid = BaseContext.getCurrentId();
        UsersTrade u = new UsersTrade();
        u.setUserId(userid);
        u.setMoney(money);
        u.setState(1);

        Snowflake snowflake = IdUtil.getSnowflake(1, 1);
        long id = snowflake.nextId();
        String Sid =  id + "";
        log.info("雪花算法 id：{}", id);
        log.info("userid: {} ", userid);
        //String openId = userMapper.FindUserById(userid).getOpenId();
        String openId = userMapper.FindUserById(userid).getOpenId();
        String prepayId = payUtil.GetSubstring(money, id , openId);

        log.info("获取的prepayId：{}",prepayId);

        long millis = System.currentTimeMillis();
        String randomString = RandomUtil.randomString(10);

        String publicKey = readKey("D:\\\\JavaseText\\\\health_02\\\\heima-health\\\\health-client\\\\src\\\\main\\\\resources\\\\rsa\\\\public_key.pem", 1024);
        String privateKey = readKey("D:\\\\JavaseText\\\\health_02\\\\heima-health\\\\health-client\\\\src\\\\main\\\\resources\\\\rsa\\\\private_key.pem", 1024);
        RSA rsaEn = new RSA(privateKey, publicKey);

        //签名
        StringBuilder builder = new StringBuilder();
        builder.append(weChatProperties.getAppid()).append("\n");
        builder.append(millis).append("\n");
        builder.append(randomString).append("\n");
        builder.append("prepay_id=" + prepayId);
        String payload = builder.toString();
        byte[] encrypt1 = rsaEn.encrypt(payload, KeyType.PrivateKey);
        String encode = Base64.encode(encrypt1);

        u.setId(Sid);
        u.setPrePayId(prepayId);
        u.setCreateTime(LocalDateTime.now());
        u.setType(1);
        u.setUserId(userid);
        usersTradeMapper.save(u);


        return OrderPaymentVO.builder()
                .paySign(encode)
                .appid(weChatProperties.getAppid())
                .packages("prepay_id=" + prepayId)
                .nonceStr(randomString)
                .signType("RSA")
                .timeStamp(millis)
                .build();

    }


    //支付结果信息
    @Override
    @Transactional
    public Boolean payCallback(String outTradeNo, Integer amount) {
        //先修改 user_trade
        UsersTrade u = usersTradeMapper.getByPrepayId(outTradeNo);

        if(u == null){
            return false;
        }

        u.setMoney(amount);
        Integer i = usersTradeMapper.update(u);

        //增加用户 余额
        UsersAccount uAccount = usersAccountMapper.getById(u.getUserId());
        if(uAccount != null){
            uAccount.setBalance(uAccount.getBalance() + amount);
            usersAccountMapper.update(uAccount);
        }else {
            UsersAccount ua = new UsersAccount();
            ua.setUserId(u.getUserId());
            ua.setBalance(amount);
            usersAccountMapper.svae(ua);
        }
        return true;

    }



    // 参数一：要读取的文件路径
    // 参数二：读取的文件长度
    private String readKey(String path, int len) throws IOException {
        // 1. 声明一个输入流
        FileInputStream fis = new FileInputStream(path);
        // 2. 声明一个字节数组，用来装从文件中读取出来的数据
        byte[] bytes = new byte[len];
        int readLen = fis.read(bytes);
        return new String(bytes);
    }


}
